﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace SkyBase
{
    /// <summary>
    /// A class to manage overlays.
    /// HOWITWORKS:
    /// Active overlays are in interfaces. Inactive (hidden) overlays are in the graveyard. Purgatory temporarily holds those
    /// that are about to become inactive. We do this because some overlays might have some operations it needs to finish before
    /// being hidden.
    /// 
    /// You can remove an overlay either through removeOverlay or through the overlay itself, just set readyToRemove to true
    /// NOTE: You can't actually do this manually, you have to keep calling preRemove until the overlay deems it fit to remove itself
    /// This is to deal with complex window animations like fading in and out (implemented) and other stuff (not implemented)
    /// Look at MainMenu.cs for an example on how overlay code should work.
    /// </summary>
    class OverlayManager
    {
        private List<Overlay> interfaces; //The list of all interfaces attached to this overlay that are to be drawn
        private List<Overlay> graveyard; //Overlays that aren't being drawn go in here
        private List<Overlay> purgatory; //Overlays that are being prepped for removal go in here
        private Vector2 cameraPos; //Tracks the camera (so that overlays aren't drawn in static locations)
        public bool hold = false; //Pause the game?

        public OverlayManager()
        {
            interfaces = new List<Overlay>();
            purgatory = new List<Overlay>();
            graveyard = new List<Overlay>();
            cameraPos = new Vector2(0, 0);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Overlay x in interfaces)
                x.Draw(spriteBatch, cameraPos);

        }

        public void Update(GameTime gameTime, Vector2 cameraPos)
        {
            this.cameraPos = cameraPos;

            //Move dying overlays to graveyard
            foreach (Overlay toRemove in purgatory)
                removeOverlay(toRemove);

            //Make sure they don't also exist in the purgatory list
            foreach (Overlay removed in graveyard)
                if (purgatory.Contains(removed))
                    purgatory.Remove(removed);

            this.hold = false;
            foreach (Overlay toUpdate in interfaces)
            {
                if (toUpdate.hold)
                    this.hold = true;

                toUpdate.Update(gameTime);

                //If the overlay decides it wants to be removed, oblige it
                if (toUpdate.readyForRemoval && !purgatory.Contains(toUpdate))
                    purgatory.Add(toUpdate);
            }

            
        }

        /// <summary>
        /// Adds the overlay to the manager. In the future this method will also sort the manager to deal with draw times.
        /// </summary>
        /// <param name="toAdd"></param>
        public void addOverlay(Overlay toAdd)
        {
            if(!interfaces.Contains(toAdd))
                interfaces.Add(toAdd);
        }

        /// <summary>
        /// Take an overlay from the graveyard and start displaying it again. (Shows overlay)
        /// </summary>
        /// <param name="toReDisplay"></param>
        public void reAttachOverlay(Overlay toReDisplay)
        {
            if(graveyard.Contains(toReDisplay))
            {
                toReDisplay.reset();
                graveyard.Remove(toReDisplay);
                interfaces.Add(toReDisplay);
            }
            else
                Debugger.debug("Error, could not find overlay " + toReDisplay.name);
        }

        /// <summary>
        /// Find an overlay in the graveyard using its name then display it again
        /// </summary>
        /// <param name="toReDisplay">The name of the hidden overlay</param>
        public void reAttachOverlay(string name)
        {
            foreach(Overlay x in graveyard)
                if (x.name == name)
                {
                    reAttachOverlay(x);
                    break;

                }
        }

        /// <summary>
        /// Removes overlay from interfaces list and moves it to the graveyard. (Hides it)
        /// </summary>
        /// <param name="toRemove">The overlay to remove</param>
        public void removeOverlay(Overlay toRemove)
        {
            if (toRemove.readyForRemoval)
            {
                interfaces.Remove(toRemove);
                graveyard.Add(toRemove);
            }
            else
            {
                toRemove.preRemove();
                if (!purgatory.Contains(toRemove))
                    purgatory.Add(toRemove);
            }
        }

        /// <summary>
        /// Unloads the given overlay from the manager (removes it entirely)
        /// </summary>
        /// <param name="toRemove"></param>
        public void unLoadOverlay(Overlay toRemove)
        {
            if (graveyard.Contains(toRemove))
                graveyard.Remove(toRemove);
            if (interfaces.Contains(toRemove))
                interfaces.Remove(toRemove);

        }
    }
}
